package com.vkapi.location;

import com.jsonutils.*;
import com.utils.framework.CollectionUtils;
import com.utils.framework.Maps;
import com.utils.framework.collections.NavigationList;
import com.utils.framework.io.IOExceptionListener;
import com.utils.framework.io.IOUtilities;
import com.utils.framework.io.Network;
import com.utils.framework.threading.Threads;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.impl.client.DefaultHttpClient;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.*;

/**
 * Created by CM on 1/22/2015.
 */
public class VkLocationApi {
    public static final String GET_COUNTRIES_URL = "https://api.vk.com/method/database.getCountries";
    public static final String GET_CITIES_URL = "https://api.vk.com/method/database.getCities";
    public static final String GET_CITY_BY_ID_URL = "https://api.vk.com/method/database.getCitiesById?city_ids=";
    private static IOExceptionListener ioExceptionListener;

    static {
        ioExceptionListener = new IOExceptionListener() {
            @Override
            public void onIOError(IOException e) {
                if (e instanceof HttpHostConnectException) {
                    Threads.sleep(1000);
                    return;
                }

                throw new RuntimeException(e);
            }
        };
    }

    private static <T> JsonRequestNavigation<T> getNavigation(String url, Map<String, Object> params, Class<T> aClass) {
        JsonRequestNavigation<T> navigation = new JsonRequestNavigation<T>(url, params, "offset",
                aClass);
        navigation.setRequestExecutor(new RequestExecutor() {
            @Override
            public String execute(String url) throws IOException {
                return Network.getUtf8StringFromUrl(url, Collections.<String, Object>emptyMap());
            }
        });
        navigation.setIOExceptionListener(ioExceptionListener);

        return navigation;
    }

    public static Iterable<VkCountry> getCountries(Language language) {
        final String url = GET_COUNTRIES_URL;

        final HashMap<String, Object> params = new HashMap<String, Object>();
        params.put("need_all", 1);
        params.put("lang", language);

        JsonRequestNavigation<VkCountry> navigation = getNavigation(url, params, VkCountry.class);

        return navigation.getNavigationIterable();
    }

    public static List<VkCountry> getAllCountries(Language language) {
        Iterable<VkCountry> countries = getCountries(language);
        return CollectionUtils.toList(countries);
    }

    public static Iterable<VkCity> getCities(final short countryId, final Language language) {
        final String url = GET_CITIES_URL;
        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("country_id", countryId);
        params.put("need_all", 1);
        params.put("lang", language);

        JsonRequestNavigation<VkCity> navigation = getNavigation(url, params, VkCity.class);
        return navigation.getNavigationIterable();
    }

    public static List<VkCity> searchCities(String query, short countryId, Language language, int maxCount)
            throws VkException {
        String url = GET_CITIES_URL;
        url += "?country_id=" + countryId + "&q=" + query + "&count=" + maxCount + "&lang=" + language;

        try {
            String json = Network.getUtf8StringFromUrl(url, new HashMap<String, Object>());
            return Json.readList(json, "response", VkCity.class);
        } catch (IOException e) {
            if (e instanceof HttpHostConnectException) {
                Threads.sleep(1000);
                return searchCities(query, countryId, language, maxCount);
            } else {
                throw new VkException(e);
            }
        }
    }

    public static VkCity getCityById(int cityId, Language language) throws VkException {
        String url = GET_CITY_BY_ID_URL + cityId + "&lang=" + language;
        List<VkCity> cities = null;
        try {
            String json = Network.getUtf8StringFromUrl(url, new HashMap<String, Object>());
            cities = Json.readList(json, "response", VkCity.class);
        } catch (IOException e) {
            throw new VkException(e);
        }
        return CollectionUtils.getFirstOrNull(cities);
    }
}
